package com.ikingtech.datav.controller;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.ikingtech.datav.api.ProjectFileApi;
import com.ikingtech.datav.enums.ProjectFileTypeEnum;
import com.ikingtech.datav.exception.ProjectFileExceptionInfo;
import com.ikingtech.datav.model.constant.FileConstant;
import com.ikingtech.datav.model.request.ProjectFileDTO;
import com.ikingtech.datav.model.request.ProjectFileDeleteDTO;
import com.ikingtech.datav.model.request.ProjectFileSearchDTO;
import com.ikingtech.datav.model.result.ProjectFileVO;
import com.ikingtech.datav.service.ProjectFileService;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.core.response.R;
import com.ikingtech.framework.sdk.dict.model.DictItemDTO;
import com.ikingtech.framework.sdk.oss.api.OssApi;
import com.ikingtech.framework.sdk.oss.model.OssFileDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.framework.sdk.web.annotation.ApiController;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * 文件管理相关接口
 *
 * @author fucb
 */
@RequiredArgsConstructor
@ApiController(value = "/files", name = "可视化大屏-文件管理", description = "可视化大屏-文件管理")
public class ProjectFileController implements ProjectFileApi {

    private final ProjectFileService projectFileService;

    private final OssApi ossApi;

    @Override
    public R<String> importResource(@RequestPart MultipartFile file) throws IOException {
        ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream(), CharsetUtil.CHARSET_GBK);
        ZipEntry nextEntry;
        int bytesRead;
        byte[] buf = new byte[1024];
        while ((nextEntry = zipInputStream.getNextEntry()) != null) {
            if (!nextEntry.isDirectory()) {
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                while ((bytesRead = zipInputStream.read(buf, 0, 1024)) > -1) {
                    outputStream.write(buf, 0, bytesRead);
                }
                // 解析并上传文件
                analysisUpload(nextEntry.getName(), outputStream.toByteArray());

                outputStream.close();
            }
            zipInputStream.closeEntry();
        }
        zipInputStream.close();
        return R.ok();
    }

    public void analysisUpload(String entryName, byte[] byteArray) {
        String[] namePath = entryName.split(StrUtil.SLASH);
        String fileName = namePath[namePath.length - 1];

        for (ProjectFileTypeEnum value : ProjectFileTypeEnum.values()) {
            if (entryName.startsWith(value.getValue())) {
                R<OssFileDTO> oss = ossApi.uploadByte(fileName, FileConstant.FILE_RESOURCE_PATH + value.getPath(), byteArray, true);
                if (oss.isSuccess()) {
                    OssFileDTO data = oss.getData();
                    projectFileService.upload(data, value, "");
                }
            }
        }
    }

    @Override
    public R<List<DictItemDTO>> type() {
        List<DictItemDTO> collect = Arrays.stream(ProjectFileTypeEnum.values()).map(x -> {
            DictItemDTO item = new DictItemDTO();
            item.setId(x.name());
            item.setLabel(x.getValue());
            return item;
        }).collect(Collectors.toList());
        return R.ok(collect);
    }

    @Override
    public R<ProjectFileDTO> upload(@RequestPart MultipartFile file,
                                    @RequestParam(required = false) ProjectFileTypeEnum type,
                                    @RequestParam(required = false) String projectId) {
        R<OssFileDTO> oss = ossApi.upload(file, FileConstant.FILE_UPLOAD_PATH, true);
        if (oss.isSuccess()) {
            OssFileDTO data = oss.getData();
            return R.ok(projectFileService.upload(data, type, projectId));
        }
        throw new FrameworkException(ProjectFileExceptionInfo.FILE_UPLOAD_FAILED);
    }

    @Override
    public R<List<ProjectFileVO>> selectByPage(@RequestBody ProjectFileSearchDTO param) {
        return R.ok(this.projectFileService.selectByPage(param).convert(entity -> Tools.Bean.copy(entity, ProjectFileVO.class)));
    }

    @Override
    public R<ProjectFileVO> getInfo(@RequestParam("id") String id) {
        return R.ok(this.projectFileService.getInfo(id));
    }

    @Override
    public R<String> delete(@RequestBody ProjectFileDeleteDTO projectFileDeleteDTO) {
        this.projectFileService.removeBatchByIds(projectFileDeleteDTO.getIds());
        return R.ok();
    }

    @Override
    public R<Boolean> existsObject(@RequestParam("path") String path) {
        return ossApi.existsObject(path);
    }

}

